<?php

if (substr(phpversion(), 0, 1) < 5)
	exit ("<b>*** PHP 5 or higher is required.</b>");

// PHP 6
if (!function_exists('get_magic_quotes_gpc'))
{
	function get_magic_quotes_gpc()
		{
			return false;
		}
}

function stripslashes_deep($value)
	{
		if (is_array($value))
			$value = array_map('stripslashes_deep', $value);

		else if (!empty($value) && is_string($value))
			$value = stripslashes($value);

		return $value;
	}

if(get_magic_quotes_gpc())
{
	stripslashes_deep($_GET);
	stripslashes_deep($_POST);
	stripslashes_deep($_REQUEST);
	stripslashes_deep($_COOKIE);
	stripslashes_deep($_SESSION);
}

function gen_salt($randnum)
	{
		for ($i = 0; $i < 20; $i++)
			$randnum .= mt_rand(0, 60);

		return md5($randnum);
	}

require_once "tfsbox_debugger.class.php";
require_once "tfsbox_config.class.php";
require_once "tfsbox_database.class.php";
require_once "tfsbox_session.class.php";
require_once "tfsbox_comments_view.class.php";

class TFsBOX extends TFsBOXDebugger
	{
		const Name = "TrueFusion sBOX v4 (Beta 3)";
		const Version = "3.9.6";

		const EmailRegex = "#^[\w\d-]+@[\w\d-]+\.[\w\.]{2,5}$#";
		const IpRegex = "#^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#";
		const NameRegex = "#^[a-zA-Z][\w\d]+$#";
		const SiteRegex = "#^http://[\w\d\.]+/$#";

		const USERNAME = "admin"; ///< User name for flatfile mode (change if you want).
		const PASSWORD = ""; ///< Password for flatfile mode; leaving it empty means no one can log in.

		static $Config;
		static $Database;
		static $Session;
		static $View;

		function __construct($config_log = null,
							 $shouts_log = null,
							 $ip_log = null,
							 $url_log = null,
							 $wordfilters_log = null,
							 $config_obj = null,
							 $db_obj = null,
							 $sess_obj = null,
							 $view_obj = null)
			{
				if (file_exists("VERSION") && is_writable("VERSION"))
					file_put_contents("VERSION", TFsBOX::Version);

				date_default_timezone_set("Etc/Universal");

				define("TFsBOX_SITE", "http://".$_SERVER['SERVER_NAME']."/");

				// Config Log
				if ($config_log)
					define("TFsBOX_CONFIG_FILE", realpath($config_log));
				else
					define("TFsBOX_CONFIG_FILE", dirname(__FILE__).'/logs/config.log');

				// Shouts Log
				if ($shouts_log)
					define("TFsBOX_SHOUTS_FILE", realpath($shouts_log));
				else
					define("TFsBOX_SHOUTS_FILE", dirname(__FILE__).'/logs/shouts.log');

				// IP Log
				if ($ip_log)
					define("TFsBOX_IP_FILE", realpath($ip_log));
				else
					define("TFsBOX_IP_FILE", dirname(__FILE__).'/logs/ipban.log');

				// URL Log
				if ($url_log)
					define("TFsBOX_URL_FILE", realpath($url_log));
				else
					define("TFsBOX_URL_FILE", dirname(__FILE__).'/logs/urlban.log');

				// Word Filters Log
				if ($wordfilters_log)
					define("TFsBOX_WORDFILTERS_FILE", realpath($wordfilters_log));
				else
					define("TFsBOX_WORDFILTERS_FILE", dirname(__FILE__).'/logs/wordfilter.log');

				// Initial setup
				if (is_subclass_of($config_obj, 'TFsBOXConfig'))
					self::$Config = new $config_obj(TFsBOX_CONFIG_FILE);
				else
					self::$Config = new TFsBOXConfig(TFsBOX_CONFIG_FILE);

				// Must come after $Config.
				if (is_subclass_of($db_obj, 'TFsBOXDatabase'))
					self::$Database = new $db_obj;
				else
					self::$Database = new TFsBOXDatabase;

				// Must come after $Database.
				if (is_subclass_of($sess_obj, 'TFsBOXSession'))
					self::$Session = new $sess_obj;
				else
					self::$Session = new TFsBOXSession;

				// Must come after $Session.
				if (is_subclass_of($view_obj, 'TFsBOXViewInterface'))
					self::$View = new $view_obj;
				else
					self::$View = new TFsBOXShoutsView;
			}

		static protected function filterAttributes($match)
			{
				$tmp = explode(" ", $match[1]);
				$elem = $tmp[0];
				unset($tmp[0]); // simplest way to remove element
				$allowed_attrs = array("href", "src", "style", "alt", "target");
				foreach ($tmp as $attr)
				{
					$attr = explode("=", $attr);
					//	If a non-allowed attribute is found,
					//	 or if a javascript command is found,
					//	 return just the element.
					if (!in_array($attr[0], $allowed_attrs)
					 || preg_match("#^\s*\"?\s*javascript\:#", strtolower($attr[1])))
						return "<$elem>";
				}

				return $match[0];
			}

		static function filterShout($shout)
			{
				$img = "";

				if (self::$Config->value("allow_images", "no") == "yes")
					$img .= "<img>";

				$shout = strip_tags($shout, "<a><span><b><i><u><s><sup><sub>$img");
				$shout = preg_replace_callback("#<([^<]+)>#i", "TFsBOX::filterAttributes", $shout);
				$shout = nl2br($shout);
				foreach (self::$Database->wordFilters() as $filter)
					$shout = preg_replace("#\b".preg_quote($filter->word)."\b#", $filter->filter, $shout);

				return $shout;
			}

		static function pathInfo()
		{
			static $path_info = NULL;
			if ($path_info === NULL)
				$path_info = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['PATH_INFO']);

			return $path_info;
		}

		function parsePathInfo()
			{
				if (TFsBOX::pathInfo() == "/tfsbox/shouts")
					define("TFsBOX_SHOUTS_ONLY", 1);

				// Report shout
				if (preg_match("#^/tfsbox/report/\d+$#", TFsBOX::pathInfo()))
				{
					$id = (int) TFsBOXSession::$PathInfo[count(TFsBOXSession::$PathInfo)-1];
					self::$Database->report($id);
					TFsBOX::redirect($_SERVER['SCRIPT_NAME']);
				}

				// Clear report
				if (preg_match("#^/tfsbox/reports/clear/\d+$#", TFsBOX::pathInfo()))
				{
					$id = (int) TFsBOXSession::$PathInfo[count(TFsBOXSession::$PathInfo)-1];
					self::$Database->clearReport($id);

					TFsBOX::redirect($_SERVER['SCRIPT_NAME']);
				}

				// Edit shout
				if (preg_match("#^/tfsbox/shouts/edit#", TFsBOX::pathInfo()))
				{
					if ($_POST['tfsbox_shout_id'] > -1)
					{
						// Assume user has requested to edit shout
						if (empty($_POST['tfsbox_shout']))
						{
							// Retrieve shout
							echo htmlentities(self::$Database->shout($_POST['tfsbox_shout_id']));
							exit(); // Prevent other data from rendering
						}

						// Assume user has finished editing shout
						else
							self::$Database->editShout($_POST['tfsbox_shout_id']);

						TFsBOX::redirect($_SERVER['SCRIPT_NAME']);
					}
				}

				// Add shout (else-if to avoid duplicate entries)
				else if (self::$Session->hasShoutReady()
					  && !self::$Session->hasErrors())
					self::$Database->addShout();

				// Delete shout
				if (preg_match("#^/tfsbox/shouts/delete/\d+#", TFsBOX::pathInfo()))
				{
					$id = (int) TFsBOXSession::$PathInfo[count(TFsBOXSession::$PathInfo)-1];
					self::$Database->deleteShout($id);

					TFsBOX::redirect($_SERVER['SCRIPT_NAME']);
				}

				// Ban IP
				if (preg_match("#^/tfsbox/ban/ip/\d+#", TFsBOX::pathInfo()))
				{
					$ip = long2ip(TFsBOXSession::$PathInfo[count(TFsBOXSession::$PathInfo)-1]);
					if (self::$Database->banIp($ip))
						TFsBOX::redirect($_SERVER['SCRIPT_NAME']);

					else TFsBOXSession::storeError("There was a problem banning the IP address <tt>$ip</tt>.");
				}

				// Ban URL
				if (TFsBOX::pathInfo() == "/tfsbox/ban/url")
				{
					if (self::$Database->banUrl(rawurldecode($_SERVER['QUERY_STRING'])))
						TFsBOX::redirect($_SERVER['SCRIPT_NAME']);

					else TFsBOXSession::storeError("There was a problem banning the URL <tt>". $_SERVER['QUERY_STRING'] ."</tt>");
				}

				// Subscribe
				if (preg_match("#^/tfsbox/subscribe/#", TFsBOX::pathInfo()))
				{
					$sub = TFsBOXSession::$PathInfo[count(TFsBOXSession::$PathInfo)-1];
					$user_id = self::$Session->userId();
					if ($user_id)
					{
						if (self::$Database->subscribe($user_id, $sub))
							TFsBOX::redirect($_SERVER['SCRIPT_NAME']);
						else
							TFsBOXSession::storeError("There was a problem subscribing to <tt>$sub</tt>.");
					}
				}

				// Log out
				if (TFsBOX::pathInfo() == "/tfsbox/logout")
					self::$Session->endSession();
			}

		static function passwordHash($username, $password)
			{
				return sha1(md5($username).md5($password));
			}

		static function redirect($location)
			{
				header('Location: '. $location);
				exit(); // Necessary?
			}

		function renderShoutBox($show_title_bar = true)
			{
				if ($show_title_bar)
					TFsBOXAbstractView::renderShoutBoxTitleBar();

				$form_position = self::$Session->formPosition();

				TFsBOXAbstractView::renderErrors((!self::$Session->hasErrors()));

				TFsBOXAbstractView::renderNotices((!self::$Session->hasNotices()));

				echo "<div id=\"tfsbox_body\">\n";

//				echo "<h2 style=\"text-align: center;\">This represents the latest source code from the <a href=\"http://code.google.com/p/tfsbox/source/checkout\">SVN trunk.</a></h2>\n";

				if (self::$Database->allowedToShout(false, false))
				{
					if ($form_position == "top"
					 || $form_position == "left")
						self::$View->renderShoutForm();
				}

				echo "<div id=\"tfsbox_content\">\n";
				self::$View->renderShouts(true, true, false);
				echo "</div>\n";

				if (self::$Database->allowedToShout(false, false))
				{
					if ($form_position == "bottom"
					 || $form_position == "right")
						self::$View->renderShoutForm();
				}

				echo "</div>\n";
			}

		function setView(TFsBOXViewInterface $view)
			{
				self::$View = $view;
			}
	}

?>
